import {httpRequest} from '@services/utils/request'
import type {DataSourceTreeNode} from '@components/business/DataSourceTree/types'
import type {CatalogVo, Column, Database, Dimension, Table} from '@/types/api'

interface Result<T> {
  code: number
  message: string
  data: T
}

// MapTree 类型（用于树结构）
interface MapTree<T> {
  id: string
  // 后端可能返回 title 或 name，这里两者都兼容
  title?: string
  name?: string
  children?: MapTree<T>[]
  nodeType?: 'SERVER' | 'CATALOG' | 'DATABASE' | 'TABLE'
  enabled?: boolean | null
  parentId?: string | null
  catalogName?: string
  data?: T
}

function mapToTreeNodes(list: MapTree<any>[], parent?: { title?: string; catalogName?: string }): DataSourceTreeNode[] {
  return (list || []).map((n) => {
    const nodeType = (n.nodeType || 'CATALOG') as any
    const isCatalog = nodeType === 'CATALOG'
    const isTable = nodeType === 'TABLE'
    const displayTitle = (n.name ?? n.title ?? '---')
    const currentCatalogName = isCatalog ? (n.catalogName ?? displayTitle) : (parent?.catalogName || parent?.title || '')
    const parentId = (n.parentId ?? parent?.title) as string | undefined

    return {
      key: n.id,
      title: displayTitle,
      id: n.id,
      nodeType,
      enabled: n.enabled ?? undefined,
      parentId,
      // 为表节点提供上层目录名，便于 API 调用
      ...(isTable ? { catalogName: currentCatalogName } : {}),
      children: n.children ? mapToTreeNodes(n.children, { title: displayTitle, catalogName: currentCatalogName }) : undefined,
    } as DataSourceTreeNode
  })
}

const u = encodeURIComponent

export const dataSourceApi = {
  async getTree(displayServer: boolean, displayTable: boolean): Promise<DataSourceTreeNode[]> {
    const res = await httpRequest<Result<MapTree<any>[]>>({
      url: '/source/tree',
      method: 'POST',
      params: { displayServer, displayTable },
    })
    return mapToTreeNodes(res.data || [])
  },

  async getCatalogs(): Promise<CatalogVo[]> {
    const res = await httpRequest<Result<CatalogVo[]>>({ url: '/source/catalogs', method: 'POST' })
    return res.data || []
  },

  async getCatalog(catalogName: string): Promise<CatalogVo> {
    const res = await httpRequest<Result<CatalogVo>>({ url: `/source/catalog/${u(catalogName)}`, method: 'POST' })
    return res.data as CatalogVo
  },

  async getDatabases(catalogName: string): Promise<Database[]> {
    const res = await httpRequest<Result<Database[]>>({ url: `/source/catalog/${u(catalogName)}/databases`, method: 'POST' })
    return res.data || []
  },

  async getEnabledDatabases(catalogName: string): Promise<Database[]> {
    const res = await httpRequest<Result<Database[]>>({ url: `/source/catalog/${u(catalogName)}/databases/enabled`, method: 'POST' })
    return res.data || []
  },

  async getDatabase(catalogName: string, databaseName: string): Promise<Database> {
    const res = await httpRequest<Result<Database>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}`, method: 'POST' })
    return res.data as Database
  },

  async getTables(catalogName: string, databaseName: string): Promise<Table[]> {
    const res = await httpRequest<Result<Table[]>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/tables`, method: 'POST' })
    return res.data || []
  },

  async getEnabledTables(catalogName: string, databaseName: string): Promise<Table[]> {
    const res = await httpRequest<Result<Table[]>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/tables/enabled`, method: 'POST' })
    return res.data || []
  },

  async getTable(catalogName: string, databaseName: string, tableName: string): Promise<Table> {
    const res = await httpRequest<Result<Table>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/table/${u(tableName)}`, method: 'POST' })
    return res.data as Table
  },

  async getColumns(catalogName: string, databaseName: string, tableName: string): Promise<Column[]> {
    const res = await httpRequest<Result<Column[]>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/table/${u(tableName)}/columns`, method: 'POST' })
    return res.data || []
  },

  async getDimensions(catalogName: string, databaseName: string, tableName: string): Promise<Dimension[]> {
    const res = await httpRequest<Result<Dimension[]>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/table/${u(tableName)}/dimensions`, method: 'POST' })
    return res.data || []
  },

  async testServer(catalogName: string): Promise<boolean> {
    const res = await httpRequest<Result<boolean>>({ url: `/source/catalog/${u(catalogName)}/test/server`, method: 'POST' })
    return !!res.data
  },
  async testJdbc(catalogName: string): Promise<boolean> {
    const res = await httpRequest<Result<boolean>>({ url: `/source/catalog/${u(catalogName)}/test/jdbc`, method: 'POST' })
    return !!res.data
  },
  async testDoris(catalogName: string): Promise<boolean> {
    const res = await httpRequest<Result<boolean>>({ url: `/source/catalog/${u(catalogName)}/test/doris`, method: 'POST' })
    return !!res.data
  },

  async syncCatalog(catalogName: string): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/sync`, method: 'POST' })
  },
  async syncDatabase(catalogName: string, databaseName: string): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/sync`, method: 'POST' })
  },

  async setCatalogEnabled(catalogName: string, enabled: boolean): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/enabled`, method: 'POST', params: { enabled } })
  },
  async setDatabaseEnabled(catalogName: string, databaseName: string, enabled: boolean): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/enabled`, method: 'POST', params: { enabled } })
  },
  async setTableEnabled(catalogName: string, databaseName: string, tableName: string, enabled: boolean): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/table/${u(tableName)}/enabled`, method: 'POST', params: { enabled } })
  },

  async updateCatalogSystemCode(catalogName: string, systemCode: string): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/systemCode`, method: 'POST', params: { systemCode } })
  },
  async updateDatabaseSystemCode(catalogName: string, databaseName: string, systemCode: string): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/systemCode`, method: 'POST', params: { systemCode } })
  },
  async updateTableSystemCode(catalogName: string, databaseName: string, tableName: string, systemCode: string): Promise<void> {
    await httpRequest<Result<void>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/table/${u(tableName)}/systemCode`, method: 'POST', params: { systemCode } })
  },

  async generateDorisScript(catalogName: string, databaseName: string, tableName: string): Promise<string> {
    const res = await httpRequest<Result<string>>({ url: `/source/catalog/${u(catalogName)}/database/${u(databaseName)}/table/${u(tableName)}/script/doris`, method: 'POST' })
    return res.data || ''
  },
}